﻿// //  ********************************************************************************
// //  Copyright (C) 2016 Sebastian Kenter. All rights reserved.
// // 
// //  Name    : MultiServerEngine | LoginServer | AccountRegisterRequestHandler.cs
// //  Created : 2016 - 02 - 16 20:53
// //  Modified: 2016 - 02 - 20 12:33
// //  ********************************************************************************

using System.Collections.Generic;
using ExitGames.Logging;
using LoginServer.Operations;
using NHibernate;
using ServerFramework.Implementation.Database;
using ServerFramework.Implementation.Database.Domain;
using ServerFramework.Implementation.Handler;
using ServerFramework.Implementation.Server;
using ServerFramework.Implementation.Telegram;
using ServerFramework.Interfaces.Server;
using ServerFramework.Interfaces.Telegram;
using TypeDefs;

namespace LoginServer.Handler.Request
{
    public class AccountRegisterRequestHandler : ServerTelegramHandler
    {
        public override TelegramHandlerTypes HandlerType => TelegramHandlerTypes.Request;
        public override byte Code => (byte) OperationCodes.Login;
        public override int? SubCode => (int?) OperationSubCodes.RegisterAccount;

        public AccountRegisterRequestHandler(ILogger logger) : base(logger)
        {
        }

        public override bool HandleTelegram(ITelegram telegram, IServerPeer serverPeer)
        {
            bool handeled = false;

            Logger.InfoFormat(
                "Trying to handle telegram of type={0}, code={1}, sub-code={2} from client={3} on server={4}",
                telegram.Type, telegram.Code, telegram.SubCode, telegram.Parameters[(byte) ParameterCodes.PeerId],
                serverPeer.ServerType);

            ServerPeer peer = serverPeer as ServerPeer;

            if (peer == null) return false;

            RegisterAccountRequestOperation contract = new RegisterAccountRequestOperation(peer.Protocol, telegram);

            if (contract.IsValid)
            {
                Account_T newAccount = new Account_T
                                     {
                                         Email = contract.Username,
                                         Givenname = contract.GivenName,
                                         Surname = contract.Surname,
                                         Salt = SecurityHelper.HashPassword(contract.Password)
                                     };

                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        IList<Account_T> accounts =
                            session.QueryOver<Account_T>().Where(c => c.Email == contract.Username).List<Account_T>();

                        if (accounts.Count > 0)
                        {
                            Logger.WarnFormat("Account for username = {0} already exists.", contract.Username);
                            handeled = true;

                            peer.SendTelegram(new ResponseTelegram(telegram.Code, telegram.SubCode, telegram.Parameters,
                                (short) ErrorCodes.AccountAlreadyRegisterd,
                                $"Account with username={contract.Username} already exists!"));
                        }
                        else
                        {
                            Logger.InfoFormat("Created account for username = {0}", contract.Username);

                            session.Save(newAccount);

                            handeled = true;

                            peer.SendTelegram(new ResponseTelegram(telegram.Code, telegram.SubCode, telegram.Parameters,
                                (short) ErrorCodes.Ok, string.Empty));
                        }

                        transaction.Commit();
                        session.Close();
                    }
                }
            }
            else
            {
                Logger.ErrorFormat("Contract error for account: {0}", contract.GetErrorMessage());
                peer.SendTelegram(new ResponseTelegram(telegram.Code, telegram.SubCode, telegram.Parameters,
                    (short) ErrorCodes.InvalidOperation, "Contract error for account creation"));
            }
            return handeled;
        }
    }
}
